import { _decorator, Asset, Component, Director, instantiate, Node, Prefab } from 'cc';
import { AssetsManager } from '../AssetsManager/AssetsManager';
const { ccclass, property } = _decorator;

type UIConfig = {
  bundleName: string;
  assetPath: string;
  cacheTime?: number;
  preload?: boolean;
};

type UICache = {
  node: Node;
  asset: Asset;
  lastUseTime: number;
};

export class UIManager {
  private static _instance: UIManager;
  private uiConfigs: Map<string, UIConfig> = new Map();
  private uiCache: Map<string, UICache> = new Map();
  private loadedBundles: Map<string, number> = new Map();
  private loadingQueues: Map<string, Promise<Prefab>> = new Map();

  private constructor() {
    // 私有构造函数
  }

  public static get instance(): UIManager {
    if (!UIManager._instance) {
      UIManager._instance = new UIManager();
    }
    return UIManager._instance;
  }

  public init(configs: Record<string, UIConfig>) {
    Object.keys(configs).forEach((uiName) => {
      const config = configs[uiName];
      this.uiConfigs.set(uiName, {
        cacheTime: -1,
        preload: false,
        ...config,
      });

      if (config.preload) {
        this.preloadUI(uiName);
      }
    })
    
    this.scheduleCacheCleanup();
  }

  private async preloadUI(uiName: string) {
    const config = this.uiConfigs.get(uiName);
    if (!config) return;

    await this.loadBundle(config.bundleName);
    await AssetsManager.instance.load<Prefab>(config.bundleName, config.assetPath, Prefab);
  }

  public async openUI(uiName: string, parentNode?: Node): Promise<Node> {
    try {
      const config = this.uiConfigs.get(uiName);
      if (!config) throw `UI配置未找到: ${uiName}`;

      // 1. 检查缓存
      const cached = this.uiCache.get(uiName);
      if (cached) {
        cached.node.active = true;
        cached.lastUseTime = Date.now();
        this.attachNode(cached.node, parentNode);
        return cached.node;
      }

      // 2. 加载资源
      const prefab = await this.loadWithLock(config);
      const node = this.createNode(uiName, prefab);
      this.attachNode(node, parentNode);
      return node;
    } catch (error) {
      console.error(`UI加载失败: ${uiName}`, error);
      throw error;
    }
  }

  private async loadBundle(bundleName: string) {
    const count = this.loadedBundles.get(bundleName) || 0;
    if (count === 0) {
      await AssetsManager.instance.preloadBundle(bundleName);
    }
    this.loadedBundles.set(bundleName, count + 1);
  }

  private async loadWithLock(config: UIConfig): Promise<Prefab> {
    const assetKey = `${config.bundleName}:${config.assetPath}`;
    if (this.loadingQueues.has(assetKey)) {
      return this.loadingQueues.get(assetKey)!;
    }

    await this.loadBundle(config.bundleName);
    const loadPromise = AssetsManager.instance.load<Prefab>(config.bundleName, config.assetPath, Prefab);
    this.loadingQueues.set(assetKey, loadPromise);

    try {
      return await loadPromise;
    } finally {
      this.loadingQueues.delete(assetKey);
    }
  }

  private createNode(uiName: string, prefab: Prefab): Node {
    const node = instantiate(prefab);
    this.uiCache.set(uiName, {
      node,
      asset: prefab,
      lastUseTime: Date.now(),
    });
    return node;
  }

  private attachNode(node: Node, parent?: Node) {
    node.parent = parent || Director.instance.getScene();
  }

  public closeUI(uiName: string) {
    const cache = this.uiCache.get(uiName);
    if (cache) cache.node.active = false;
  }

  public releaseUI(uiName: string) {
    const cache = this.uiCache.get(uiName);
    if (!cache) return;

    const config = this.uiConfigs.get(uiName)!;
    cache.node.destroy();
    AssetsManager.instance.release(config.bundleName, config.assetPath);
    this.uiCache.delete(uiName);
  }

  private scheduleCacheCleanup() {
    setInterval(() => {
      this.uiCache.forEach((cache, uiName) => {
        const config = this.uiConfigs.get(uiName)!;
        if (config.cacheTime !== -1 && Date.now() - cache.lastUseTime > config.cacheTime) {
          this.releaseUI(uiName);
        }
      });
    }, 60_000);
  }
}